package sg.techstudio.suntec.dao;

import java.util.Calendar;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import sg.techstudio.suntec.object.ContactDevice;
import sg.techstudio.suntec.object.RestEventContactObj;
import sg.techstudio.suntec.object.WifiAccountObj;

@Repository("eDao")
@Transactional
public class EventContactDao {
	private static final Log log = LogFactory.getLog(EventContactDao.class);
	
	@Autowired
	private SessionFactory sessionFactory;
	
	@SuppressWarnings("unchecked")
	public RestEventContactObj getEventContact(Long id) {
		log.debug("getEventContact() entry");
		Criteria c = sessionFactory.getCurrentSession().createCriteria(RestEventContactObj.class);
		c.add(Restrictions.eq("id", id));
		List<RestEventContactObj> list = c.list();
		return list!=null&&!list.isEmpty()?list.get(0):null;
	}
	
	@SuppressWarnings("unchecked")
	public List<ContactDevice> getContactDeviceRemoveDuplicate() {
		log.debug("getContactDeviceRemoveDuplicate() entry");
		Session ses = sessionFactory.getCurrentSession();
		Criteria c = ses.createCriteria(ContactDevice.class);
		List<ContactDevice> cdList = c.list();
		if(cdList==null || cdList.isEmpty())
			return cdList;
		Set<String> macSet = new HashSet<String>();
		List<ContactDevice> retList = new LinkedList<ContactDevice>();
		for(ContactDevice cd: cdList) {
			if(macSet.contains(cd.getMac())) {
				ses.delete(cd);
				continue;
			}
			retList.add(cd);
			macSet.add(cd.getMac());
		}
		return retList;
	}
	
	public RestEventContactObj saveEventContact(RestEventContactObj re) {
		log.debug("saveContact() entry");
		Session ses = sessionFactory.getCurrentSession();
		re.setUpdatedDate(Calendar.getInstance().getTime());
		ses.saveOrUpdate(re);
		return re;
	}
	
	public void saveContactDevice(ContactDevice cd) {
		log.debug("saveContactDevice() entry");
		Session ses = sessionFactory.getCurrentSession();
		ses.saveOrUpdate(cd);
	}
	
	public void deleteContactDevice(ContactDevice cd) {
		log.debug("deleteContactDevice() entry");
		Session ses = sessionFactory.getCurrentSession();
		ses.delete(cd);
	}
	
	public void deleteWifiAccount(Collection<WifiAccountObj> wifiCol) {
		log.debug("updateEventContact() entry");
		if(wifiCol==null)
			return;
		Session ses = sessionFactory.getCurrentSession();
		for(WifiAccountObj w: wifiCol)
			ses.delete(w);
	}
	
	public RestEventContactObj updateEventContact(RestEventContactObj re) {
		log.debug("updateEventContact() entry");
		Session ses = sessionFactory.getCurrentSession();
		re.setUpdatedDate(Calendar.getInstance().getTime());
		ses.update(re);
		return re;
	}
	
	@SuppressWarnings("unchecked")
	public RestEventContactObj findEventContact(RestEventContactObj re) {
		log.debug("findEventContact() entry");
		Session ses = sessionFactory.getCurrentSession();
		Criteria c = ses.createCriteria(RestEventContactObj.class);
		c.add(Restrictions.eq("extId", re.getExtId()));
		c.add(Restrictions.eq("type", re.getType()));
		List<RestEventContactObj> ret = c.list();
		return ret==null || ret.isEmpty()?null:ret.get(0);
	}
	
	@SuppressWarnings("unchecked")
	public RestEventContactObj findEventByWifiAccount(WifiAccountObj w) {
		log.debug("findEventByWifiAccount() entry");
		if(w==null || w.getId()==null)
			return null;
		Session ses = sessionFactory.getCurrentSession();
		Criteria c = ses.createCriteria(RestEventContactObj.class);
		Criteria c2 = c.createCriteria("wifiAccoutList");
		c2.add(Restrictions.eq("id", w.getId()));
		List<RestEventContactObj> ret = c2.list();
		return ret==null || ret.isEmpty()?null:ret.get(0);
	}
	
	public boolean checkPasswordExist(String password) {
		log.debug("checkPasswordExist() entry");
		Session ses = sessionFactory.getCurrentSession();
		Criteria c = ses.createCriteria(WifiAccountObj.class);
		c.add(Restrictions.eq("wifiPassword", password));
		return 0<(Long)c.setProjection(Projections.rowCount()).uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public WifiAccountObj getWifiAccountObj(String username) {
		log.debug("getWifiAccountObj() entry");
		Session ses = sessionFactory.getCurrentSession();
		Criteria c = ses.createCriteria(WifiAccountObj.class);
		c.add(Restrictions.eq("wifiUsername", username));
		List<WifiAccountObj> ret = c.list();
		return ret==null || ret.isEmpty()?null:ret.get(0);
	}
	
	public Long countContactEvent(String search) {
		log.debug("countContactEvent() entry");
		Criteria c = sessionFactory.getCurrentSession().createCriteria(RestEventContactObj.class);
		c.add(Restrictions.eq("active", true));
		if(!StringUtils.isBlank(search)) {
			c.add(Restrictions.or(Restrictions.eq("extId", NumberUtils.toLong(search))
					, Restrictions.or(Restrictions.ilike("name", "%"+search+"%"))));
		}
		
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		c.setProjection(Projections.rowCount());
		return (Long) c.uniqueResult();
	}
	
	@SuppressWarnings("unchecked")
	public List<RestEventContactObj> getContactEventList(String search, int firstResult, int maxResults){
		log.debug("getContactEventList() entry");
		Criteria c = sessionFactory.getCurrentSession().createCriteria(RestEventContactObj.class);
		c.add(Restrictions.eq("active", true));
		if(!StringUtils.isBlank(search)) {
			c.add(Restrictions.or(Restrictions.eq("extId", NumberUtils.toLong(search))
					, Restrictions.or(Restrictions.ilike("name", "%"+search+"%"))));
		}
		
		c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
		c.addOrder(Order.desc("id"));
		c.setFirstResult(firstResult);
		c.setMaxResults(maxResults);
		return c.list();
	}
}
